#include "stdafx.h"
#include "board.h"
#include "patternNode.h"
#include "uctnode.h"
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "chrono.h"

Board::Board(int size) {
	_size = size;
    	
    _theBoard = new BoardPosition*[_size];
	for(int i=0; i<_size; i++) 
		*(_theBoard+i)=new BoardPosition[_size];

    for(int i=0; i<_size; i++) 
        for(int j=0; j<_size; j++) {
			_theBoard[i][j].setEmpty();
			_theBoard[i][j].setLabel(-1);
			_theBoard[i][j].setAlive(false);
        }
}

Board::Board(Board *b) {
	//to clone the Board
	_size = b->getSize();
    
    _theBoard = new BoardPosition*[_size];
	for(int i=0; i<_size; i++) 
		*(_theBoard+i)=new BoardPosition[_size];

    for(int i=0; i<_size; i++) 
        for(int j=0; j<_size; j++) {
			if(b->isEmpty(i,j))
				_theBoard[i][j].setEmpty();
			else {
				if(b->isBlack(i,j))
					_theBoard[i][j].setBlack();
				else
					_theBoard[i][j].setWhite();
			}
			_theBoard[i][j].setLabel(b->getPosition(i,j).getLabel());
			_theBoard[i][j].setAlive(b->getPosition(i,j).isAlive());
        }
}

Board::Board(Board &b) {
	
}

Board::~Board(){
	for (int i=0; i < _size; i++)
	delete[] _theBoard[i];
	delete[] _theBoard;
	_theBoard = NULL;
}

bool Board::isEmpty(int x, int y){
	return _theBoard[x][y].isEmpty();
}
bool Board::isBlack(int x, int y){
	return _theBoard[x][y].isBlack();
}

bool Board::boardIsEmpty(){
	for (int i =0; i<this->getSize()-1; i++)
	{
		for (int j =0; j<this->getSize()-1; j++)
		{
			if(!(this->isEmpty(i,j)))
			{
				return false;
			}
		}
	}
	return true;
}

Board Board::operator=(Board& A){
	Board* B=new Board(A);
	return *B;
}

int Board::getSize() {
	return _size; 
}

Position Board::getPosition(int row, int col) {
	return _theBoard[row][col];
}

void Board::setEmpty(int row, int col) {
	_theBoard[row][col].setEmpty();
}

void Board::setBlack(int row, int col) {
	_theBoard[row][col].setBlack();
}

void Board::setWhite(int row, int col) {
	_theBoard[row][col].setWhite();
}

void Board::setAlive(int row, int col, bool alive) {
	_theBoard[row][col].setAlive(alive);
}

void Board::displayBoard() {
	//Display the board stones
	printf("\n  a b c d e f g h i   a b c d e f g h i   a b c d e f g h i  \n");
	for(int i=0; i<this->getSize(); i++){
		printf("%i ", i+1);
		for(int j=0; j<this->getSize(); j++) {
			if(this->isEmpty(i,j))
				printf (". ");
			else { 
				if (this->isBlack(i,j))
					printf ("x ");
				else
					printf ("o ");
			}
		}
		printf("%i ", i+1);
		//display labels
		for(int j=0; j<this->getSize(); j++) {
			if(this->isEmpty(i,j))
				printf (". ");
			else {
				if (this->getPosition(i,j).getLabel()>0 && this->getPosition(i,j).getLabel()<10)
					printf("%i ",this->getPosition(i,j).getLabel());
				else
					printf("%i",this->getPosition(i,j).getLabel());
			}
		}
		printf("%i ", i+1);
		//display "alive" status
		for(int j=0; j<this->getSize(); j++) {
			if(this->isEmpty(i,j))
				printf (". ");
			else 
				printf("%i ",this->getPosition(i,j).isAlive());
		}
		printf("%i\n", i+1);
	}
	printf("  a b c d e f g h i   a b c d e f g h i   a b c d e f g h i  \n\n");
}

void Board::playGame(){
	//To play the game for testing, you can input yourself your movement 
	int row, col, prevX=0, prevY=0, prevCaptX=-1, prevCaptY=-1, captX=-1, captY=-1;
	int passWhite=0, passBlack=0;
	bool error, error1, color=BLACK;
	do {	printf("prevCaptX=%i, prevCaptY=%i \n",prevCaptX, prevCaptY);//loop untill both players pass consecutively twice
		if (color)
			printf("Black: place your stone ");
		else 
			printf("White: place your stone ");
		do {	//loop untill a valid move is played or a pass in requested if there is no valid move left 
			printf("sequence bool validMove() ...");
			if (this->validMove(color)) {
				do {	//loop checking if the chosen move is within the board limits
					error=false; error1=false;
					cin>>row;cin>>col;
					if (row<0 || col<0 || row>this->getSize()-1 || col>this->getSize()-1) {
						error=true;
						printf("Place not valid!\n");
						if (color)
							printf("Black: Choose another place ");
						else
							printf("White: Choose another place ");
					}
				}while (error);
				if (this->isEmpty(row,col)) {
					if (!this->simpleKo(row, col, color, prevX, prevY, prevCaptX, prevCaptY)) {printf("testko  \n");
						if (!this->suicideCheck(row, col, color)) {printf("testsuicide  \n");
							if (!this->checkIfEye(row, col)) {printf("testeye  \n");							
								if (color) {
									this->setBlack(row, col);
									passBlack=0;
								}
								else {
									this->setWhite(row, col);
									passWhite=0;
								}
								this->initAlive();
								this->setAlive(row, col, true);
								this->setLabel();
								this->setChainAlive(this->getPosition(row ,col).getLabel());
								this->checkIfAliveTemp();
								this->capture(captX, captY);
								printf("captX=%i  captY=%i\n",captX,captY);
								this->displayBoard();
								error=false;
							}
							else {
								this->displayBoard();
								error=true;
								printf("It's an eye! Don't play there !\n");
								if (color)
									printf("Black: Choose another place ");
								else 
									printf("White: Choose another place ");
							}
						}
						else {
							this->displayBoard();
							error=true;
							printf("error : suicide!\n");
							if (color)
								printf("Black: Choose another place ");
							else
								printf("White: Choose another place ");
						}
					}
					else {
						this->displayBoard();
						error=true;
						printf("Ko! Can't play there !\n");
						if (color)
							printf("Black: Choose another place ");
						else
							printf("White: Choose another place ");
					}
				}
				else {
					error=true;
					printf("error : place not empty!\n");
					if (color)
						printf("Black: Choose another place ");
					else
						printf("White: Choose another place ");
				}
			}
			else {
				printf("No more valid place to play!\n");
				if (color) {
					passBlack++;
					error1=true;
					printf("Black passes\n");
				}
				else {
					passWhite++;
					error1=true;
					printf("White passes\n");
				}					
			}
			if (!error && !error1) {				//error required because if there is an error this loop will be recrossed again with the same color. In the mean time,
				prevX=row; prevY=col;				//prevX, prevY, prevCaptX, prevCaptY would have been updated and the simpleKo test in the next loop wouldn't be accurate !
				prevCaptX=captX; prevCaptY=captY;	//error1 required to avoid refreshing prevX, prevY, prevCaptX and prevCaptY when a player passes.
			}
		}
		while (error);
		color=!color;
	}
	while(passBlack<2 && passWhite<2);
	printf("THE END !!!! ");
}

void Board::playGame(bool UCTColor){
	//To play the game against UCT for testing, you can input yourself your movement 
	int row, col, prevX=-1, prevY=-1, prevCaptX=-1, prevCaptY=-1, captX=-1, captY=-1, resultX=-1, resultY=-1;
	int passWhite=0, passBlack=0;
	bool error, error1, color=BLACK;
	do {
		if (color)
			printf("Black: place your stone ");
		else 
			printf("White: place your stone ");
		do {	//loop untill a valid move is played or a pass in requested if there is no valid move left 
			if (this->validMove(color)) {
				bool pass=false;
				if (color==UCTColor) {
					UCTNode *uct = NULL;
					uct->launchUCT(!color, this, prevX, prevY, prevCaptX, prevCaptY, resultX, resultY, pass);
					if (!pass)
					{
						row = resultX; col = resultY;
						printf("Found a move! (%i,%i)",row,col);
						//delete uct;
					}
					else {
						pass=true; }
				}
				else {	
					do {	//loop checking if the chosen move is within the board limits
						error=false; error1=false;
						cin>>row;cin>>col;
						if (row<0 || col<0 || row>this->getSize()-1 || col>this->getSize()-1) {
							error=true;
							printf("Place not valid!\n");
							if (color)
								printf("Black: Choose another place ");
							else
								printf("White: Choose another place ");
						}
					}while (error);
				}
				if (!pass) {
					if (this->isEmpty(row,col)) {
						if (!this->simpleKo(row, col, color, prevX, prevY, prevCaptX, prevCaptY)) {//printf("testko  \n");
							if (!this->suicideCheck(row, col, color)) {//printf("testsuicide  \n");
								if (!this->checkIfEye(row, col)) {//printf("testeye  \n");							
									if (color) {
										this->setBlack(row, col);
										passBlack=0;
									}
									else {
										this->setWhite(row, col);
										passWhite=0;
									}
									this->initAlive();
									this->setAlive(row, col, true);
									this->setLabel();
									this->setChainAlive(this->getPosition(row ,col).getLabel());
									this->checkIfAliveTemp();
									this->capture(captX, captY);
									this->displayBoard();
									error=false;
								}
								else {
									this->displayBoard();
									error=true;
									printf("It's an eye! Don't play there !\n");
									if (color)
										printf("Black: Choose another place ");
									else 
										printf("White: Choose another place ");
								}
							}
							else {
								this->displayBoard();
								error=true;
								printf("error : suicide!\n");
								if (color)
									printf("Black: Choose another place ");
								else
									printf("White: Choose another place ");
							}
						}
						else {
							this->displayBoard();
							error=true;
							printf("Ko! Can't play there !\n");
							if (color)
								printf("Black: Choose another place ");
							else
								printf("White: Choose another place ");
						}
					}
					else {
						error=true;
						printf("error : place not empty!\n");
						if (color)
							printf("Black: Choose another place ");
						else
							printf("White: Choose another place ");
					}
				}
				else {
					if (color) {
						passBlack++;
						error1=true;
						printf("Black passes\n");
					}
					else {
						passWhite++;
						error1=true;
						printf("White passes\n");
					}
				}
			}
			else {
				printf("No more valid place to play!\n");
				if (color) {
					passBlack++;
					error1=true;
					printf("Black passes\n");
				}
				else {
					passWhite++;
					error1=true;
					printf("White passes\n");
				}					
			}
			if (!error && !error1) {				//error required because if there is an error this loop will be recrossed again with the same color. In the mean time,
				prevX=row; prevY=col;				//prevX, prevY, prevCaptX, prevCaptY would have been updated and the simpleKo test in the next loop wouldn't be accurate !
				prevCaptX=captX; prevCaptY=captY;	//error1 required to avoid refreshing prevX, prevY, prevCaptX and prevCaptY when a player passes.
			}
		}
		while (error);
		color=!color;
	}
	while(passBlack<2 && passWhite<2);
	printf("THE END !!!! ");
}

bool Board::launchMonteCarlo(bool lastPlayedColor, int prevX, int prevY, int prevCaptX, int prevCaptY) {
	//Launch Monte-Carlo sequence (radom moves till the end of the game)
	//if Monte-Carlo is launched when the board is empty just pass any values for prevX and prevY
	//e.g.: launchMonteCarlo(WHITE,0,0); (WHITE cause Black is expected to play first!)
	Board *tempMT= new Board(this);
	bool color=!lastPlayedColor;
	bool error, error1, end=false;
	int row, col, captX=-1, captY=-1;
	int passBlack=0, passWhite=0, compt=0;//int stopBlack=0, stopWhite=0;
	//printf("launching Monte-Carlo sequence... ");
	//Chrono t;
	//t.iGo();
	do {
		do {
			error=false; error1=false;
			//printf("launching NodeList ...\n");
			NodeList* list = new NodeList(tempMT->validMoveList(color, prevX, prevY, prevCaptX, prevCaptY));
			
			/*int size1 = list->getSize();
			printf("size = %i \n",size1);
			Node* temp = list->getFirstNode();int compt=0;
			while (compt<size1) {
				compt++;
				printf("noeud%i :(%i,%i) ",compt ,temp->getRow(), temp->getCol());
				temp=temp->getNextNode();
			}*/
			//if (stopBlack >2 || stopWhite>2)
			//	while(1);
			//else{
			//	if (color){stopBlack++;}
			//	else{stopWhite++;}
			//}
			/*int test;
			cin >> test;//*/
			//Sleep(400);

			Node* firstNode = list->getFirstNode();
			if (firstNode != NULL) {
				do {
					error=false;
					int size = list->getSize();
					/*if (color)
						printf("Black: Place your stone ");
					else
						printf("White: Place your stone ");*/
					

					/* generate numbers: */
					int number = rand()%size;
					//printf("\nRandom = %i :  (size=%i)\n", number,size);
					Node* index = firstNode;
					while (number>0) {
						index = index->getNextNode();
						number--;
					}
					row=index->getRow();
					col=index->getCol();//printf("%i %i \n",row, col);

					if (row<0 || col<0 || row>tempMT->getSize()-1 || col>tempMT->getSize()-1) {
						error=true;
						/*printf("Place not valid!\n");
						if (color)
							printf("Black: Choose another place ");
						else
							printf("White: Choose another place ");*/
					}
				}while (error);
				delete list;
				list = NULL;
				if (tempMT->isEmpty(row,col)) {	//printf("testempty  OK\n");
					if (!tempMT->simpleKo(row, col, color, prevX, prevY, prevCaptX, prevCaptY)) {	//printf("testko  OK\n");
						if (!tempMT->suicideCheck(row, col, color)) {	//printf("testsuicide  OK\n");
							if (!tempMT->checkIfEye(row, col)) {	//printf("testeye  OK\n");
								if (color) {
									tempMT->setBlack(row, col);
									passBlack=0;
									//stopBlack=0;
								}
								else {
									tempMT->setWhite(row, col);
									passWhite=0;
									//stopWhite=0;
								}
								tempMT->initAlive();
								tempMT->setAlive(row, col, true);
								tempMT->setLabel();
								tempMT->setChainAlive(tempMT->getPosition(row ,col).getLabel());
								tempMT->checkIfAliveTemp();
								tempMT->capture(captX, captY);
								/*if (t.iStop()>500)
								{
									tempMT->displayBoard();
									compt++;
								}*/
								//tempMT->displayBoard();
								//if (compt>9) while(1);//end=true;
								error=false;
							}
							else {
								//tempMT->displayBoard();
								error=true;
								/*printf("It's an eye! Don't play there !\n");
								if (color)
									printf("Black: Choose another place ");
								else
									printf("White: Choose another place ");*/
							}
						}
						else {
							//tempMT->displayBoard();
							error=true;
							/*printf("error : suicide!\n");
							if (color)
								printf("Black: Choose another place ");
							else
								printf("White: Choose another place ");*/
						}
					}
					else {
						//tempMT->displayBoard();
						error=true;
						/*printf("Ko! Can't play there !\n");
						if (color)
							printf("Black: Choose another place ");
						else
							printf("White: Choose another place ");*/
					}
				}
				else {
					error=true;
					/*printf("error : place not empty!\n");
					if (color)
						//printf("Black: Choose another place ");
					else
						//printf("White: Choose another place ");*/
				}
			}
			else {
				//printf("No more valid place to play!\n");
				if (color) {
					//printf("Black passes\n");
					error1=true;
					passBlack++;
				}
				else {
					//printf("White passes\n");
					error1=true;
					passWhite++;
				}
			}
			if (!error && !error1) {				//error required because if there is an error this loop will be recrossed again with the same color. In the mean time,
				prevX=row; prevY=col;				//prevX, prevY, prevCaptX, prevCaptY would have been updated and the simpleKo test in the next loop wouldn't be accurate !
				prevCaptX=captX; prevCaptY=captY;	//error1 required to avoid refreshing prevX, prevY, prevCaptX and prevCaptY when a player passes.
			}
			if (passBlack>1 && passWhite>1)
				end=true;
		}
		while (error);
		color=!color;
        //printf("Press any key");
		//int wait;
		//cin >> wait ;
	}
	while (!end);
	bool score = tempMT->areaScoring();
	delete tempMT;
	tempMT = NULL;
	//printf("... end of Monte-Carlo sequence.\n");
	return score;
}

void Board::initLabel() {
	//Reset all labels to -1, used before refreshing each stone's label
	for (int i=this->getSize()-1; i>=0; i--)
		for (int j=this->getSize()-1; j>=0; j--)
			_theBoard[i][j].setLabel(-1);
}

void Board::setLabel() {
	//Set label for each stone after each move
	int newLabel=0;
	this->initLabel();
	for (int i=this->getSize()-1; i>=0; i--)
	{
		for (int j=this->getSize()-1; j>=0; j--)
		{
			if(this->getPosition(i,j).getLabel() == -1 && !this->isEmpty(i,j))
			{	
				_theBoard[i][j].setLabel(++newLabel);
				//printf("sequence label %i : ",newLabel);
				this->recurLabel(i,j);
				//printf("fin\n");
			}
		}
	}
}

void Board::recurLabel(int posx, int posy) {
	//Recursive tracking for labelling stones by groups
	int i= posx;
	int j= posy;
	if(i-1>=0)
		if (!this->isEmpty(i-1,j) && this->isBlack(i,j)==this->isBlack(i-1,j) && this->getPosition(i-1,j).getLabel()==-1)
		{// up
			//printf("up ");
			_theBoard[i-1][j].setLabel(this->getPosition(i,j).getLabel());
			this->recurLabel(i-1,j);
			//printf("back ");
		}
	if(j-1>=0)
		if (!this->isEmpty(i,j-1) && this->isBlack(i,j)==this->isBlack(i,j-1) && this->getPosition(i,j-1).getLabel()==-1)
		{// left
			//printf("left ");
			_theBoard[i][j-1].setLabel(this->getPosition(i,j).getLabel());
			this->recurLabel(i,j-1);
			//printf("back ");
		}
	if(i+1<this->getSize())
		if (!this->isEmpty(i+1,j) && this->isBlack(i,j)==this->isBlack(i+1,j) && this->getPosition(i+1,j).getLabel()==-1)
		{// down
			//printf("down ");
			_theBoard[i+1][j].setLabel(this->getPosition(i,j).getLabel());
			this->recurLabel(i+1,j);
			//printf("back ");
		}
	if(j+1<this->getSize())
		if (!this->isEmpty(i,j+1) && this->isBlack(i,j)==this->isBlack(i,j+1) && this->getPosition(i,j+1).getLabel()==-1)
		{// right
			//printf("right ");
			_theBoard[i][j+1].setLabel(this->getPosition(i,j).getLabel());
			this->recurLabel(i,j+1);
			//printf("back ");
		}
}

void Board::setChainAlive(int label){
	//Set the group with the number "label" to "alive" status
	for (int i=this->getSize()-1; i>=0; i--)
	{
		for (int j=this->getSize()-1; j>=0; j--)
		{
			if (this->getPosition(i,j).getLabel()==label)
			{
				_theBoard[i][j].setAlive(true);
			}
		}
	}
}

void Board::checkIfAlive() {
	//Check if a group is alive by resetting alive status of all stones to false
	//then update (set) alive status of each group with one or more liberties
    initAlive();
    for (int i=this->getSize()-1; i>=0; i--)
    {
        for (int j=this->getSize()-1; j>=0; j--)
        {
            if(this->getPosition(i,j).isAlive() == false && !this->isEmpty(i,j))
            {
                bool ok=false;
				if(j-1 >= 0 && !ok)
                {//check left neighbour
                    if(this->isEmpty(i,j-1))
                    {
                        setChainAlive(this->getPosition(i,j).getLabel());
						ok=true;
                    }
                }
                if(i-1 >= 0 && !ok)
                {//check upper neighbour
                    if(this->isEmpty(i-1,j))
                    {
                        setChainAlive(this->getPosition(i,j).getLabel());
						ok=true;
                    }
                }
                if(j+1 <this->getSize() && !ok)
                {//check right neighbour
                    if(this->isEmpty(i,j+1))
                    {
                        setChainAlive(this->getPosition(i,j).getLabel());
						ok=true;
                    }
                }
                if(i+1 <this->getSize() && !ok)
                {//check bottom neighbour   
                    if(this->isEmpty(i+1,j))
                    {
                        setChainAlive(this->getPosition(i,j).getLabel());
                    }
                }
            }
        }
    }
}

void Board::checkIfAliveTemp() {
	//Same as checkIfAlive() but without initAlive() in it
	//required in order to play in suicidal positions but with a capture as result
    for (int i=this->getSize()-1; i>=0; i--)
    {
        for (int j=this->getSize()-1; j>=0; j--)
        {
            if(this->getPosition(i,j).isAlive() == false && !this->isEmpty(i,j))
            {
                bool ok=false;
				if(j-1 >= 0 && !ok)
                {//check left neighbour
                    if(this->isEmpty(i,j-1))
                    {
                        setChainAlive(this->getPosition(i,j).getLabel());
						ok=true;
                    }
                }
                if(i-1 >= 0 && !ok)
                {//check upper neighbour
                    if(this->isEmpty(i-1,j))
                    {
                        setChainAlive(this->getPosition(i,j).getLabel());
						ok=true;
                    }
                }
                if(j+1 <this->getSize() && !ok)
                {//check right neighbour
                    if(this->isEmpty(i,j+1))
                    {
                        setChainAlive(this->getPosition(i,j).getLabel());
						ok=true;
                    }
                }
                if(i+1 <this->getSize() && !ok)
                {//check bottom neighbour   
                    if(this->isEmpty(i+1,j))
                    {
                        setChainAlive(this->getPosition(i,j).getLabel());
                    }
                }
            }
        }
    }
}

void Board::initAlive() {
	//Reset the "alive" status to false for each stone
	for (int i=this->getSize()-1; i>=0; i--)
	{
		for (int j=this->getSize()-1; j>=0; j--)
		{
			_theBoard[i][j].setAlive(false);
		}
	}
}

int Board::capture() {
	//remove dead stones and return the number of captured stones
	int captured=0;
	for (int i=this->getSize()-1; i>=0; i--)
	{
		for (int j=this->getSize()-1; j>=0; j--)
		{
			if(!this->getPosition(i,j).isEmpty() && !this->getPosition(i,j).isAlive())
			{
				_theBoard[i][j].setEmpty();
				captured++;
			}
		}
	}
	return captured;
}

void Board::capture(int &captX, int &captY) {
	//remove dead stones and return the number of captured stones
	int captured=0;
	for (int i=this->getSize()-1; i>=0; i--)
	{
		for (int j=this->getSize()-1; j>=0; j--)
		{
			if(!this->getPosition(i,j).isEmpty() && !this->getPosition(i,j).isAlive())
			{
				_theBoard[i][j].setEmpty();
				captured++;
				if (captured == 1) {
					captX = i; captY = j;
				}
				else {
					captX = -1; captY = -1;
				}
			}
		}
	}
	//return captured;
}

/*bool Board::validCapture(bool color) {
	//check if captured stones are opponent's stones
	Board *tempBoard = new Board(this);
	for (int i=tempBoard->getSize()-1; i>=0; i--)
	{
		for (int j=tempBoard->getSize()-1; j>=0; j--)
		{
			if (!tempBoard->isEmpty(i,j))
			{
				if (!tempBoard->getPosition(i,j).isAlive() && tempBoard->isBlack(i,j)==color)
				{	// if among captured stones there is one with the same color as the played stone --> SUICIDE !
					delete tempBoard;
					tempBoard = NULL;
					return false;
				}
			}
		}
	}
	delete tempBoard;
	tempBoard = NULL;
	return true;
}*/

bool Board::suicideCheck (int posx, int posy, bool isBlack) {
	//Check (return true) if the move at (posx,posy) is a suicide
	Board *tempBoard = new Board(this); 
	if (isBlack)
		tempBoard->setBlack(posx, posy);
	else
		tempBoard->setWhite(posx, posy);
	tempBoard->initAlive();
	tempBoard->setAlive(posx, posy, true);
	tempBoard->setLabel();
	tempBoard->setChainAlive(tempBoard->getPosition(posx,posy).getLabel());
	tempBoard->checkIfAliveTemp();
	tempBoard->capture();
	tempBoard->setLabel();
	tempBoard->checkIfAlive();
	if (tempBoard->getPosition(posx, posy).isAlive())
	{//NO SUICIDE
		//tempBoard->displayBoard();
		delete tempBoard;
		tempBoard = NULL;
		return false;
	}
	else
	{//SUICIDE
		//tempBoard->displayBoard();
		delete tempBoard;
		tempBoard = NULL;
		return true;
	}
}	 

bool Board::checkIfEye (int posx, int posy) {
	//check (return true) if player is playing in his own eye
	bool corner=false;	//helps to check if there is more than one free corner or one color difference in the corner
	bool color;			//helps to compare every stone's color between each other
	if(posx-1>=0)		//it is long but easy to understand
	{	
		if (!this->isEmpty(posx-1,posy))
		{
			color=this->isBlack(posx-1,posy);
			//printf("Color = %i ",color);
		}
		else
		{
			//printf("NOT AN EYE 1\n");
			return false;
		}
	}
	else
	{
		if (!this->isEmpty(posx+1,posy))
		{
			color=this->isBlack(posx+1,posy);
			//printf("Color = %i ",color);
		}
		else
		{
			//printf("NOT AN EYE 2\n");
			return false;			
		}
	}
	if(posx-1>=0)
	{
		if (!this->isEmpty(posx-1,posy))
		{//check above
			if(this->isBlack(posx-1,posy)!=color)
			{
				//printf("NOT AN EYE 3\n");
				return false;
			}
		}
		else
		{
			return false;
			//printf("NOT AN EYE 4\n");
		}													// ///////// //
		if (posy-1>=0)										// 1 | 2 | 3 //
		{//check upper left corner	(1)						// -   -   - //
			if (!this->isEmpty(posx-1,posy-1))				// 4 | 5 | 6 //
			{												// -   -   - //	
				if(this->isBlack(posx-1,posy-1)!=color)		// 7 | 8 | 9 //
				{											// ///////// //
					if(!corner) // if the upper left corner (1) color is different from (2),(4),(6) and (8) 
					{			// corner is set to true, if it happens one more time then it's not an eye.
						corner=true;
						//printf("corner 1 is different color ");
					}
					else
					{
						//printf("corner 1 is different color ");
						//printf("NOT AN EYE 5\n");
						return false;
					}
				}
			}
			else	// if the upper left corner (1) is empty corner is set to true.
			{
				if(!corner)
				{
					corner=true;
					//printf("corner 1 is empty ");
				}
				else
				{
					//printf("corner 1 is empty ");
					//printf("NOT AN EYE 6\n");
					return false;
				}
			}
		}
		if (posy+1<this->getSize())
		{//check upper right corner
			if (!this->isEmpty(posx-1,posy+1))
			{
				if(this->isBlack(posx-1,posy+1)!=color)
				{
					if(!corner)
					{
						corner=true;
						//printf("corner 3 is different color ");
					}
					else
					{
						//printf("corner 3 is different color ");
						//printf("NOT AN EYE 7\n");
						return false;
					}
				}
			}
			else
			{
				if(!corner)
				{
					corner=true;
					//printf("corner 3 is empty ");
				}
				else
				{
					//printf("corner 3 is empty ");
					//printf("NOT AN EYE 8\n");
					return false;
				}
			}
		}
	}
	if (posx+1<this->getSize())
	{
		if (!this->isEmpty(posx+1,posy))
		{//check below
			if(this->isBlack(posx+1,posy)!=color)
			{
				//printf("NOT AN EYE 8\n");
				return false;
			}
		}
		else
		{
			//printf("NOT AN EYE 9\n");
			return false;
		}
		if (posy-1>=0)
		{//check bottom left corner
			if (!this->isEmpty(posx+1,posy-1))
			{
				if(this->isBlack(posx+1,posy-1)!=color)
				{
					if(!corner)
					{
						//printf("corner 7 is different color ");
						corner=true;
					}
					else
					{
						//printf("corner 7 is different color ");
						//printf("NOT AN EYE 10\n");
						return false;
					}
				}
			}
			else
			{
				if(!corner)
				{
					//printf("corner 7 is empty ");
					corner=true;
				}
				else
				{
					//printf("corner 7 is empty ");
					//printf("NOT AN EYE 11\n");
					return false;
				}
			}
		}
		if (posy+1<this->getSize())
		{//check bottom right corner
			if (!this->isEmpty(posx+1,posy+1))
			{
				if(this->isBlack(posx+1,posy+1)!=color)
				{
					if(!corner)
					{
						//printf("corner 9 is different color ");
						corner=true;
					}
					else
					{
						//printf("corner 9 is different color ");
						//printf("NOT AN EYE 12\n");
						return false;
					}
				}
			}
			else
			{
				if(!corner)
				{
					//printf("corner 9 is empty ");
					corner=true;
				}
				else
				{
					//printf("corner 9 is empty ");
					//printf("NOT AN EYE 13\n");
					return false;
				}
			}
		}
	}
	if (posy-1>=0)
	{//check left 
		if (!this->isEmpty(posx,posy-1))
		{
			if(this->isBlack(posx,posy-1)!=color)
			{
				//printf("NOT AN EYE 14\n");
				return false;
			}
		}
		else
			return false;
	}
	if (posy+1<this->getSize())
	{//check right
		if (!this->isEmpty(posx,posy+1))
		{
			if(this->isBlack(posx,posy+1)!=color)
			{
				//printf("NOT AN EYE 15\n");
				return false;
			}
		}
		else
		{
			//printf("NOT AN EYE 16\n");
			return false;
		}
	}
	//printf("IT'S AN EYE\n");
	return true;
}

bool Board::validMove (bool color) {
	//Check (return true) if there is at least one valid move left to play
	for (int i=this->getSize()-1; i>=0; i--)
	{
		for (int j=this->getSize()-1; j>=0; j--)
		{
			if(this->isEmpty(i,j))
			{
				if(!this->checkIfEye(i,j))
				{
					if(i-1>=0)
					{
						if(color!=this->isBlack(i-1,j))
						{
							if(!this->suicideCheck (i, j, color)) 
							{
								//if(!this->simpleKo(i, j, color, prevX, prevY, prevCaptX, prevCaptY))
								//{
									return true;
								//}
							}
						}
					}
					else
					{
						if(color!=this->isBlack(i+1,j))
						{
							if(!this->suicideCheck (i, j, color)) 
							{
								//if(!this->simpleKo(i, j, color, prevX, prevY, prevCaptX, prevCaptY))
								//{
									return true;
								//}
							}
						}
					}
				}
			}
		}
	}
	return false;
}

NodeList Board::validMoveList (bool color, int prevX, int prevY, int prevCaptX, int prevCaptY) {
	//Return a list with all valid places left to play
	NodeList* list= new NodeList();
	for (int i=this->getSize()-1; i>=0; i--)
	{
		for (int j=this->getSize()-1; j>=0; j--)
		{
			if(this->isEmpty(i,j))
			{//printf("\n pos (%i;%i) prevCaptX=%i , prevCaptY=%i ",i,j,prevCaptX,prevCaptY);
				if(!this->checkIfEye(i,j))
				{//printf("test eye ok ");
					if(i-1>=0)
					{
						if(color!=this->isBlack(i-1,j))
						{
							if(!this->suicideCheck (i, j, color)) 
							{//printf("test suicide ok ");
								if(!this->simpleKo(i, j, color, prevX, prevY, prevCaptX, prevCaptY))
								{//printf("test ko ok ");
									Node* node = new Node(i,j);
									list->addNode(node);
								}
							}
						}
						else
						{
							if(!this->suicideCheck (i, j, color)) 
							{//printf("test suicide ok ");
								if(!this->simpleKo(i, j, color, prevX, prevY, prevCaptX, prevCaptY))
								{//printf("test ko ok ");
									Node* node = new Node(i,j);
									list->addNode(node);
								}
							}
						}
					}
					else
					{
						if(color!=this->isBlack(i+1,j))
						{
							if(!this->suicideCheck (i, j, color)) 
							{
								if(!this->simpleKo(i, j, color, prevX, prevY, prevCaptX, prevCaptY))
								{
									Node* node = new Node(i,j);
									list->addNode(node);
								}
							}
						}
						else
						{
							if(!this->suicideCheck (i, j, color)) 
							{
								if(!this->simpleKo(i, j, color, prevX, prevY, prevCaptX, prevCaptY))
								{
									Node* node = new Node(i,j);
									list->addNode(node);
								}
							}
						}
					}
				}
			}
		}
	}
	return *list;
}

bool Board::areaScoring () //Chinese scoring
{
	int whiteScore=0;
	int blackScore=0;
	for (int i=this->getSize()-1; i>=0; i--)
	{
		for (int j=this->getSize()-1; j>=0; j--)
		{
			if(!this->isEmpty(i,j))
			{
				if(this->isBlack(i,j))
					blackScore++;
				else
					whiteScore++;
			}
			else
			{
				if(this->checkIfEye(i,j))
				{
					if(i-1>=0)
					{
						if(this->isBlack(i-1,j))
							blackScore++;
						else
							whiteScore++;
					}
					else
					{
						if(this->isBlack(i+1,j))
							blackScore++;
						else
							whiteScore++;
					}
				}
			}
		}
	}
	if (blackScore>whiteScore) {
		//printf("Black : %i, White: %i --> Black Wins !\n", blackScore, whiteScore);
		return true;
	}
	else {
		//printf("Black : %i, White: %i --> White Wins !\n", blackScore, whiteScore);
		return false;
	}
}

bool Board::simpleKo (int posx, int posy, bool isBlack, int prevPosX, int prevPosY, int prevCaptX, int prevCaptY)
{//printf("For posx(%i,%i) prevCaptX=%i prevCaptY=%i",posx,posy,prevCaptX,prevCaptY);
	if (this->boardIsEmpty() || prevCaptX==-1 ||prevCaptY==-1){	//check if the board is empty  to avoid the case "first move --> no previous move"
		return false;		}									//and if prevCaptX, -Y ==-1 (means that the number of captured stones was != 1) 
	else 
	{
		Board *tempBoard = new Board(this); 
		if (isBlack)
			tempBoard->setBlack(posx, posy);
		else
			tempBoard->setWhite(posx, posy);
		
		tempBoard->initAlive();
		tempBoard->setAlive(posx, posy, true);
		tempBoard->setLabel();
		tempBoard->setChainAlive(tempBoard->getPosition(posx,posy).getLabel());
		tempBoard->checkIfAliveTemp();
		if(!tempBoard->getPosition(prevPosX,prevPosY).isAlive()) {	//check if last played move is still alive
			int captured=tempBoard->capture();						//if it's not remove all dead stones
			if (captured==1) {								//if there is only one dead stone 
				if (prevCaptX==posx && prevCaptY==posy) {	//we need to check if posx and posy are not the coordinates of the last captured stone. 
					delete tempBoard;						//if it is the case then it's KO !
					tempBoard = NULL;
					return true;
				}
				else {										//if it's not the case then it's OK ! ;-)
					delete tempBoard;
					tempBoard = NULL;
					return false;
				}
			}
			else {	//if capture=0 or >1, then it's never KO !
				delete tempBoard;
				tempBoard = NULL;
				return false;
			}
			
		}
		else {	//if the last played stone is still alive --> no KO !
			delete tempBoard;
			tempBoard = NULL;
			return false;
		}
	}
}
